package org.senseframework.support.open.api.controller.encrypt;

import org.senseframework.support.core.utils.DateUtils;
import org.senseframework.support.core.utils.DigestUtils;
import org.senseframework.support.open.api.exception.ApiException;
import org.senseframework.support.open.api.service.ApiDefinition;

import java.util.Arrays;

/**
 * Author lanjian
 * Email  jianlan@iflytek.com
 */
public class DefaultApplicationEncryptHandler implements ApplicationEncryptHandler<ExchangeResponse> {
    private String keyStorePath;
    private String alias;
    private String password;
    private ExchangeToken exchangeToken;
    private int expire;
    private String chartset;
    private boolean open = true;

    public boolean isOpen() {
        return open;
    }

    public void setOpen(boolean open) {
        this.open = open;
    }

    public ExchangeToken getExchangeToken() {
        return exchangeToken;
    }

    public void setExchangeToken(ExchangeToken exchangeToken) {
        this.exchangeToken = exchangeToken;
    }

    public String getChartset() {
        return chartset;
    }

    public void setChartset(String chartset) {
        this.chartset = chartset;
    }

    public int getExpire() {
        return expire;
    }

    public void setExpire(int expire) {
        this.expire = expire;
    }

    public String getKeyStorePath() {
        return keyStorePath;
    }

    public void setKeyStorePath(String keyStorePath) {
        this.keyStorePath = keyStorePath;
    }

    public String getAlias() {
        return alias;
    }

    public void setAlias(String alias) {
        this.alias = alias;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }


    @Override
    public ExchangeResponse generate(byte[] content) {
        try {
            byte[] decrypt = SecurityHelper.decryptByPrivateKey(content, keyStorePath, alias, password);
            int start = 0;
            int end = Constants.ENCRYPT_KEY_LENGTH;
            byte[] key = Arrays.copyOfRange(decrypt, start, end);
            byte appKeyLength = decrypt[Constants.ENCRYPT_KEY_LENGTH];
            end += 1;
            start = end;
            end += appKeyLength;
            byte[] appKey = Arrays.copyOfRange(decrypt, start, end);
            String appKeyString = new String(appKey, Constants.DEFAULT_CHARSET);
            String aesPassword = new String(key, "UTF-8");
            start = end;
            end += Constants.ENCRYPT_CHECKINFO_LENGTH;
            byte[] check = Arrays.copyOfRange(decrypt, start, end);
            start = end;
            end = decrypt.length;
            byte[] encrypt = Arrays.copyOfRange(decrypt, start, end);
            byte[] thisCheck = SecurityHelper.decryptAES(aesPassword, encrypt);
            boolean success = Arrays.equals(check, thisCheck);
            if (success) {
                //生成并保存token
                String token = exchangeToken.generate(aesPassword, appKeyString, expire);
                return new ExchangeResponse(expire, token, DateUtils.nowDateTime());
            }
            throw new ApiException("generate error", ApiDefinition.ENCYTPT_EROOR);
        } catch (Exception ex) {
            throw new ApiException("generate error", ApiDefinition.ENCYTPT_EROOR, ex);
        }
    }

    @Override
    public String decode(String key, String body) {
        try {
            byte[] content = body.getBytes(chartset);
            byte[] content_ = SecurityHelper.decryptAES(key, DigestUtils.decodeBase64(content));
            return new String(content_, chartset);
        } catch (Exception ex) {
            throw new EncryptException("decode error", ex);
        }

    }

    @Override
    public String encode(String key, String body) {
        try {
            byte[] content = body.getBytes(chartset);
            byte[] _content = SecurityHelper.encryptAES(key, content);
            return DigestUtils.encodeBase64(_content);
        } catch (Exception ex) {
            throw new EncryptException("encode error", ex);
        }

    }

    @Override
    public ExchangeKey findExchangeKey(String token) {
        ExchangeKey exchangeKey = exchangeToken.from(token);
        if (exchangeKey == null) {
            throw new EncryptException("findKeyInfo error keyInfo is null");
        }
        exchangeKey.validate();
        return exchangeKey;
    }

    @Override
    public boolean open() {
        return isOpen();
    }
}
